package org.example.myprojectbackend.filter;

import com.auth0.jwt.interfaces.DecodedJWT;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.example.myprojectbackend.utils.Const;
import org.example.myprojectbackend.utils.JwtUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * @ClassName JwtAuthorityFilter
 * @Author liupanpan
 * @Date 2025/1/3
 * @Description
 */

/**
 * 解析jwt,校验jwt
 * 用于对请求头中的jwt令牌进行校验的工具，为当前请求添加用户验证信息
 * 并将用户的id存放在请求对象属性中，方便后续使用
 */
@Component
public class JwtAuthorityFilter extends OncePerRequestFilter {

    @Resource
    JwtUtils jwtUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        //获取请求头jwt信息
        String authHeader = request.getHeader("Authorization");
        //解析jwt，得到解析好的jwt对象DecodedJWT
        DecodedJWT decodedJWT = jwtUtils.verifyJwt(authHeader);
        if (decodedJWT != null) {
            //将解析好的jwt对象 封装到 UserDetails 中
            UserDetails userDetails = jwtUtils.toUserDetails(decodedJWT);
            // 创建一个身份验证令牌(security内部的验证token)并将其存储在安全上下文中，以便后续的请求可以访问认证信息
            // 创建一个UsernamePasswordAuthenticationToken实例，包含用户详细信息和权限
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            // 设置请求的详细信息
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            // 将认证信息存储在安全上下文中
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            //将用户的id存放在请求对象属性中，方便后续使用
            request.setAttribute(Const.ATTR_USER_ID, jwtUtils.toId(decodedJWT));
        }
        filterChain.doFilter(request, response);
    }
}
